import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/services.dart';
import 'package:image/image.dart' as img;
import 'package:path_provider/path_provider.dart';
import 'package:uuid/uuid.dart';

import 'bean/ocr_result.dart';
import 'bean/ocr_result.dart';
import 'bean/ocr_result.dart';
import 'bean/ocr_results.dart';
import 'logger.dart';

class PaddleOcr {
  static const MethodChannel _channel = const MethodChannel('paddle_ocr');

  static Future<String?> get platformVersion async {
    final String? version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }

  static Future<dynamic> ocrFromImage(String imagePath, {bool isRotate = false, bool forwardRotation = true, double degree = 90.0, String? ocr_type,bool isPrint = false}) async {
    try {
      initLogger();
      String ocrImagePath = imagePath;
      if (isRotate) {
        var imageData = File(imagePath).readAsBytesSync();
        img.Image image = img.decodeImage(imageData)!;
        img.Image ocrImage = img.copyRotate(image, forwardRotation ? degree : -degree);
        Directory dir = await (getExternalStorageDirectory() as FutureOr<Directory>);
        String path = dir.path;
        File rotate90ImageFile = File('$path/rotate/${Uuid().v4().toString()}.jpg');
        rotate90ImageFile.parent.createSync(recursive: true);
        rotate90ImageFile.writeAsBytesSync(img.encodeJpg(ocrImage));
        ocrImagePath = rotate90ImageFile.path;
      }
      final String ocrStr = await (_channel.invokeMethod('ocrFromImage', {'imagePath': ocrImagePath}));
      return {"success": true,'code':'0', "message": "识别成功", "ocrResult": await _processOcrResult(ocrStr, ocr_type: ocr_type,isPrint: isPrint)};
    } catch (e,stack) {
      logger.e(e);
      logger.e(stack);
      if (e is PlatformException) {
        return {"success": false,'code':e.code, "message": e.message, "ocrResult": null};
      }
      return {"success": false,'code':'-999', "message": e.toString(), "ocrResult": null};
    }
  }

  static Future<OcrResultInfo?> _processOcrResult(String ocrStr, {String? ocr_type, bool isPrint = false}) async {
    try{
      OcrResultInfo ocrResultInfo = OcrResultInfo.fromJson({'ocrResults': jsonDecode(ocrStr.replaceAll(RegExp(r'[\\r\n]{1,2}'), '')), 'ocr_type': 'OTHER'});
      if(isPrint) {
        ocrResultInfo.ocrResults!.forEach((element) {
          print(element.toString());
        });
      }
      if (ocrResultInfo.ocrResults!.length == 0) {
        ocrResultInfo.ocr_type = 'EMPTY';
        return ocrResultInfo;
      }
      if (ocr_type != null && ocr_type == 'ID_CARD') {
        ocrResultInfo.ocr_type = ocr_type;
        return _processIDCardOcrResult(ocrResultInfo, isPrint: isPrint);
      }
      return ocrResultInfo;
    } catch(e, stack) {
      logger.e(e);
      logger.e(stack);
      return null;
    }
  }

  static Future<OcrResultInfo> _processIDCardOcrResult(OcrResultInfo ocrResultInfo, {bool isPrint = false}) async {
    try{
      final results = ocrResultInfo.ocrResults!;
      final ocrRes = results.firstWhere((element) => element.name!.contains('签发机关'), orElse: () => OcrResult());
      bool isFront = ocrRes.name!.isEmpty;
      if (isFront) {
        final ocrResFirstLine = results[0];
        final ocrResSecondLine = results.firstWhere((element) => element != null && element.name!.contains(RegExp('性别|民族')), orElse: () => OcrResult());
        final lineHeight = ocrResFirstLine.bounds![3].y! - ocrResFirstLine.bounds![0].y!;
        final lineSpace =  ocrResSecondLine.bounds![0].y! - ocrResFirstLine.bounds![3].y!;
        if(isPrint) {
          print(lineHeight);
          print(lineSpace);
        }
        String name = '';
        String? sex = '';
        String? nation = '';
        String? birthday = '';
        String addr = '';
        String? no = '';
        int resultsLen = results.length;
        for (var index = 0; index < resultsLen; index++) {
          final result = results[index];
          final text_region = result.bounds!;
          final tlx = text_region[0].x;
          final tly = text_region[0].y;
          final trx = text_region[1].x;
          final triy = text_region[1].y;
          final bly = text_region[3].y!;
          if (bly < results[0].bounds![3].y! + lineSpace/2) {
            if (isPrint) {
              print('1-');
              print(result);
              print(result.name!.replaceAll('姓名', ''));
            }
            final n = result.name!.replaceAll('姓名', '');
            if (n.length > 0) {
              name = n;
            }
          } else if (bly < results[0].bounds![3].y! + lineSpace/2 + lineHeight + lineSpace) {
            if (isPrint) {
              print('2-');
              print(result);
            }
            final r = RegExp(r'性别(.)民族(.)');
            final r1 = RegExp(r'(.)民族(.)');
            final m = r.allMatches(result.name!).toList();
            final m1 = r1.allMatches(result.name!).toList();
            if (m.length > 0 || m1.length > 0) {
              sex = m[0].group(1);
              nation = m[0].group(2);
            }
          } else if (bly < results[0].bounds![3].y! + lineSpace/2 + (lineHeight + lineSpace) * 2) {
            if (isPrint) {
              print('3-');
              print(result);
              print(result.name == '出生');
              print(result.name == '');
            }
            final r = RegExp(r'[\d]{4}年[\d]{1,2}月[\d]{1,2}日');
            final m = r.allMatches(result.name!.replaceAll('出生', '')).toList();
            if (m.length > 0) {
              birthday = m[0].group(0);
            }
          } else if (bly < results[0].bounds![3].y! + lineSpace/2 + (lineHeight + lineSpace) * 4) {
            if (isPrint) {
              print('4-');
              print(result);
            }
            if (result.name != '住址' && result.name != '佳址') {
              if (result.name!.length > 0) {
                addr += result.name!;
                print(result.name);
              }
            }
          } else if (bly < results[0].bounds![3].y! + lineSpace + (lineHeight + lineSpace) * 6) {
            if (isPrint) {
              print('5-');
              print(result);
            }
            final r = RegExp(r'[\d]{18}');
            final m = r.allMatches(result.name!.replaceAll('公民身份证', '')).toList();
            if (m.length > 0) {
              no = m[0].group(0);
            }
          }
        }
        if (isPrint) {
          print('姓名:$name');
          print('性别:$sex');
          print('民族:$nation');
          print('生日:$birthday');
          print('住址:$addr');
          print('身份证号:$no');
        }
        OcrResultInfo ocrResultInfoNew = OcrResultInfo.fromJson({
          'ocrResults': [
            OcrResult(name: name).toJson(),
            OcrResult(name: sex).toJson(),
            OcrResult(name: nation).toJson(),
            OcrResult(name: birthday).toJson(),
            OcrResult(name: addr).toJson(),
            OcrResult(name: no).toJson(),
          ],
          'ocr_type': 'ID_CARD'
        });
        return ocrResultInfoNew;
      } else {
        String agent = '';
        String limitStart = '';
        String limitEnd = '';
        String limit = '';
        final lineHeight = ocrRes.bounds![3].y! - ocrRes.bounds![0].y!;
        double lineSpace =  0;

        int resultsLen = results.length;
        for (var index = 0; index < resultsLen; index++) {
          final result = results[index];
          final text_region = result.bounds!;
          final tlx = text_region[0].x;
          final tly = text_region[0].y;
          final trx = text_region[1].x;
          final triy = text_region[1].y;
          final bly = text_region[3].y;
          if (result.name == ocrRes.name) {
            lineSpace = results[index + 1].bounds![0].y! - ocrRes.bounds![3].y!;
            final a = result.name!.replaceAll('签发机关', '');
            if (a.length > 0 && a.contains('公安局')) {
              agent = a;
            }
          }else if (bly! < ocrRes.bounds![3].y! + lineHeight/2 || result.name!.contains(RegExp('公安局|签发机关'))) {
            if (isPrint) {
              print('1-');
              print(result);
            }
            final a = result.name!.replaceAll('签发机关', '');
            if (a.length > 0 && a.contains('公安局')) {
              agent = a;
            }
          } else {
            if (isPrint) {
              print('2-');
              print(result);
            }
            final r = RegExp(r'(([\d]{4})[\.:]?([\d]{2})[\.:]?([\d]{2}))[-]?(([\d]{4})[\.:]?([\d]{2})[\.:]?([\d]{2}))');
            final m = r.allMatches(result.name!).toList();
            if (m.length > 0) {
              limitStart = m[0].group(2)! + '-' + m[0].group(3)! + '-' + m[0].group(4)!;
              limitEnd = m[0].group(6)! + '-' + m[0].group(7)! + '-' + m[0].group(8)!;
              limit = limitStart + ' ' + limitEnd;
            }
          }
        }
        if (isPrint) {
          print('签发机关:$agent');
          print('有效期限:$limit');
        }

        OcrResultInfo ocrResultInfoNew = OcrResultInfo.fromJson({
          'ocrResults': [
            OcrResult(name: agent).toJson(),
            OcrResult(name: limitStart).toJson(),
            OcrResult(name: limitEnd).toJson(),
          ],
          'ocr_type': 'ID_CARD'
        });
        return ocrResultInfoNew;
      }
    } catch(e, stack) {
      logger.e(e);
      logger.e(stack);
      return ocrResultInfo;
    }
  }
}
